import { INVALID_VALUE } from '../../Core/CoreDefine';
import { ObjectWrap } from '../../Core/FrameEx/ES5Ex';
import { REquireItem } from '../Data/RunTime/RunRaw/RItemAttach';
import RJXItem from '../Data/RunTime/RunRaw/RJXItem';
import { JXMath } from './../../conventions/JXCommon';
import { CompareEnum, CURRENCY, ITEM_TYPE } from './../Common/Define';
import GameMgr from './GameMgr';
export interface IHeroSortFunc {
	(a: IHeroData, b: IHeroData, ext?: any): CompareEnum;
}

export interface SHeroSortFunc {
	(a: SHeroDataRaw, b: SHeroDataRaw, ext?: any): CompareEnum;
}

export interface EquipSortFunc {
	(a: REquireItem, b: REquireItem, ext?: any): CompareEnum;
}

/**热数据排列 */
export class IHeroSort {
	/** 比较卡牌星级 */
	public static sortStart(a: IHeroData, b: IHeroData): CompareEnum {
		let tempalteA = GameMgr.heroData.getRaw<SHeroDataRaw>(a.tableId);
		let templateB = GameMgr.heroData.getRaw<SHeroDataRaw>(b.tableId);
		if (tempalteA.birthStar > templateB.birthStar) return CompareEnum.CGreater;
		else if (tempalteA.birthStar < templateB.birthStar) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	/**比较等级*/
	public static sortLvUp(a: IHeroData, b: IHeroData): CompareEnum {
		if (a.lv > b.lv) return CompareEnum.CGreater;
		else if (a.lv < b.lv) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	/**比较战力 */
	public static sortZhanli(a: IHeroData, b: IHeroData): CompareEnum {
		// let arrB: Array<Array<number>> = GameMgr.lUserData.getHeroBuff(a.tableId);
		let zhanliA = JXMath.getZhanli(a.propts);
		let zhanliB = JXMath.getZhanli(b.propts);
		if (zhanliA > zhanliB) return CompareEnum.CGreater;
		else if (zhanliA < zhanliB) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	/** 组合排序 */
	public static sorts(sortFuncs: IHeroSortFunc[], a: IHeroData, b: IHeroData): CompareEnum {
		for (let func of sortFuncs) {
			let ret = func(a, b);
			if (ret == CompareEnum.CEQual) continue;
			return ret;
		}
		return CompareEnum.CEQual;
	}


	/**比较装备属性 */
	public static sortEquipZhanli(a: REquireItem, b: REquireItem): CompareEnum {
		let zhanliA = JXMath.getEquipZhanli(a.propts.values());
		let zhanliB = JXMath.getEquipZhanli(b.propts.values());
		if (zhanliA > zhanliB) return CompareEnum.CGreater;
		else if (zhanliA < zhanliB) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	public static sortsEquire(sortFuncs: EquipSortFunc[], a: REquireItem, b: REquireItem): CompareEnum {
		for (let func of sortFuncs) {
			let ret = func(a, b);
			if (ret == CompareEnum.CEQual) continue;
			return ret;
		}
		return CompareEnum.CEQual;
	}
}

/**静态数据排列 */
export class SHeroSort {
	/** 比较卡牌星级 */
	public static sortStart(a: SHeroDataRaw, b: SHeroDataRaw): CompareEnum {
		let tempalteA = a;
		let templateB = b;
		if (tempalteA.birthStar > templateB.birthStar) return CompareEnum.CGreater;
		else if (tempalteA.birthStar < templateB.birthStar) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	/**比较卡牌等级*/
	public static sortTrait(a: SHeroDataRaw, b: SHeroDataRaw): CompareEnum {
		if (a.trait > b.trait) return CompareEnum.CGreater;
		else if (a.trait < b.trait) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	/**比较战力 */
	public static sortZhanli(a: SHeroDataRaw, b: SHeroDataRaw): CompareEnum {
		let zhanliA = JXMath.getZhanli(a.property);
		let zhanliB = JXMath.getZhanli(b.property);
		if (zhanliA > zhanliB) return CompareEnum.CGreater;
		else if (zhanliA < zhanliB) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	/**比较解锁未解锁碎片数量 */
	public static sortChip(a: SHeroDataRaw, b: SHeroDataRaw): CompareEnum {
		let chipA = GameMgr.RBagData.getMegreItems(a.id, ITEM_TYPE.PROP);
		let chipB = GameMgr.RBagData.getMegreItems(b.id, ITEM_TYPE.PROP);
		if (chipA > chipB) return CompareEnum.CGreater;
		else if (chipA < chipB) return CompareEnum.CLess;
		else return CompareEnum.CEQual;
	}

	/** 组合排序 */
	public static sorts(sortFuncs: SHeroSortFunc[], a: SHeroDataRaw, b: SHeroDataRaw): CompareEnum {
		for (let func of sortFuncs) {
			let ret = func(a, b);
			if (ret == CompareEnum.CEQual) continue;
			return ret;
		}
		return CompareEnum.CEQual;
	}
}

export class HeroMgr extends ObjectWrap {
	private static _instance: HeroMgr = null;
	public static ins(): HeroMgr {
		if (this._instance == null) {
			this._instance = new HeroMgr();
		}
		return this._instance;
	}

	constructor() {
		super();
	}

	public checkHaveHeroCanGotoBattle() {
		let noHero = GameMgr.rHeroData.checkInNoHero();
		if (noHero) {
			return true;
		}
		let isFull = GameMgr.rHeroData.checkBattleTeamisFull();
		if (isFull) {
			return false;
		}
		let heros = GameMgr.rHeroData.heroDatas.values<IHeroData>();
		for (let index = 0; index < heros.length; index++) {
			const element = heros[index];
			let inTeam = GameMgr.rHeroData.checkHeroIsInBattle(element.tableId)
			if (!inTeam) return true;
		}
	}

	/**分解英雄碎片 */
	public getChipNeedByStar(num: number) {
		let obj: starLv = {
			lv: 0,
			count: num
		}
		let rise: number = 1;
		let star = num / 5;
		var starCount = null;
		if (star + obj.lv > rise) {
			obj.lv = parseInt(star.toString());
			if (star % 1 == 0) {
				obj.lv = star - 1;
			}
			let num1 = (star % 1).toFixed(1);
			if (num1 == '0.0') {
				starCount = 5;
			} else {
				starCount = Number(num1) / 0.2;
			}
			obj.count = Math.ceil(starCount);
		}
		// console.log('obj', obj);
		return obj
	}

	public checkHeroCanGrow(heroId: number, isTupo = false) {
		let hero = GameMgr.rHeroData.getHero(heroId)
		if (!hero) { return false; }
		let curData = GameMgr.lvData.getRaw<SLvDataRaw>(hero.lv);
		//下一个等级数据
		let nextData = GameMgr.lvData.getRaw<SLvDataRaw>(hero.lv + 1);
		if (!nextData) { return false };
		if (nextData.quality != curData.quality && hero.exp >= nextData.exp && isTupo) {
			let jxitem = new RJXItem([201, ITEM_TYPE.PROP, 1]);
			let result = GameMgr.itemMgr.testCost(jxitem);
			return result.enough;
		} else if (hero.exp >= nextData.exp) {
			let jxItem = new RJXItem([CURRENCY.GOLD, ITEM_TYPE.CURRENCY, nextData.gold])
			let result = GameMgr.itemMgr.testCost(jxItem);
			return result.enough;
		}
		return false;
	}


	public checkHavaHeroCanGrow(isTupo = false) {
		let heros = GameMgr.rHeroData.getAllHeros().values<IHeroData>();
		let can = false;
		for (let i = 0; i < heros.length; i++) {
			let hero = heros[i];
			can = this.checkHeroCanGrow(hero.tableId, isTupo);
			if (can) break;
		}
		return can;
	}

	public checkHavaHeroCanAddStar() {
		let heros = GameMgr.rHeroData.getAllHeros().values<IHeroData>();
		let can = false;
		for (let i = 0; i < heros.length; i++) {
			let hero = heros[i];
			can = this.checkHeroCanAddStar(hero.tableId);
			if (can) break;
		}
		return can;
	}

	public checkHaveHeroUnlockByChip() {
		let heros = GameMgr.heroData.getHeroTrue();
		let can = false;
		for (let i = 0; i < heros.length; i++) {
			let hero = heros[i];
			can = this.checkHeroCanUnlockByChip(hero.id);
			if (can) break;
		}
		return can;
	}

	public checkHeroCanUnlockByChip(heroId: number) {
		let hero = GameMgr.rHeroData.getHero(heroId);
		if (hero) { return false }
		let raw = GameMgr.heroData.getRaw<SHeroDataRaw>(heroId);
		let count = raw.unlockStar;
		let jxItem = new RJXItem([heroId, ITEM_TYPE.PROP, count])
		let result = GameMgr.itemMgr.testCost(jxItem);
		return result.enough;
	}


	public checkHeroCanAddStar(heroId: number) {
		let hero = GameMgr.rHeroData.getHero(heroId);
		if (!hero) { return false }
		let raw = GameMgr.heroData.getRaw<SHeroDataRaw>(hero.tableId);
		if (hero.star >= raw.star.length * 5) {
			return false;
		} else {
			let starInfo = this.getChipNeedByStar(hero.star)
			let count = raw.star[starInfo.lv];
			let jxItem = new RJXItem([hero.tableId, ITEM_TYPE.PROP, count])
			let result = GameMgr.itemMgr.testCost(jxItem);
			return result.enough;
		}
	}
	// 判断所有英雄是否有穿戴
	public checkHavaHeroCanWear() {
		let allHero = GameMgr.rHeroData.getAllHeros().values<IHeroData>()
		for (let i = 0; i < allHero.length; i++) {
			let hero = allHero[i];
			let isBast = this.checkHeorBastEquip(hero);
			if (isBast) {
				return isBast;
			}
		}
		return false;
	}

	//判断单个英雄是否有装备可以穿戴
	public checkHeorBastEquip(hero: IHeroData) {
		let allEquip = GameMgr.RBagData.getHeroEquip(hero.tableId);
		let equips = [...allEquip.book, ...allEquip.equip];
		let isBase = false;
		for (let i = 0; i < equips.length; i++) {
			let equip = equips[i]
			if (hero.equips.indexOf(equip) != INVALID_VALUE) continue
			let equipData = GameMgr.RBagData.getEquipDataById(equips[i])
			if (equipData.wear != INVALID_VALUE) continue;
			let seat = equipData.itemData.raw.seat;
			if (seat > 2) {
				isBase = this.checkEquipIsBast(hero.equips[3], equips[i], hero.lv);
				if (!isBase) {
					isBase = this.checkEquipIsBast(hero.equips[4], equips[i], hero.lv);
				}
				if (!isBase) {
					isBase = this.checkEquipIsBast(hero.equips[5], equips[i], hero.lv);
				}
			} else {
				isBase = this.checkEquipIsBast(hero.equips[seat], equips[i], hero.lv)
			}
			if (isBase) break;
		}
		return isBase;
	}

	public checkEquipIsBast(heroEquipId, equipId, lv) {
		let equipData = GameMgr.RBagData.getEquipDataById(equipId);
		if (lv < equipData.itemData.raw.lv) return false
		if (heroEquipId === "-1" || !heroEquipId) {
			return true;
		} else {
			let equip = GameMgr.RBagData.getEquipDataById(equipId);
			let hero = GameMgr.RBagData.getEquipDataById(heroEquipId);
			return hero.getZhanli() < equip.getZhanli();
		}
	}
}